//
// Created by Administrator on 2022/2/22.
//
#include <iostream>
#include <string>

#ifndef CLION_CPP_T_PURE_VITURAL_FUNCTION_CLASS_H
#define CLION_CPP_T_PURE_VITURAL_FUNCTION_CLASS_H

namespace pure_vitrual_func_class_test{
    using  std::cout;
    using  std::cin;
    using  std::endl;
    using  std::string;
    using  fmtflags = std::ios_base::fmtflags;
    using  std::streamsize;

    static const int CLIENTS = 4;
    //测试函数
    void test();


    //纯虚函数，类似Java的interface
    class AcctABC{
        private:
            string fullName;
            long acctNum;
            double balance;
        protected:
            struct Formatting{
                fmtflags flag;
                streamsize pr;
            };
            const std::string &FullName()const {return fullName;}
            long AcctNum()const{return acctNum;}
            //格式化相关-设置格式化
            inline Formatting setFormat()const{
                Formatting f;
                f.flag = cout.setf(std::ios_base::fixed,std::ios_base::floatfield);
                f.pr = cout.precision(2);
                return f;
            };
            //重置为格式化
            inline void Restore(Formatting &f)const{
                cout.setf(f.flag,std::ios_base::floatfield);
                cout.precision(f.pr);
            };
        public:
            inline AcctABC(const string &s="Nullbody",long an = -1,double bal = 0.0){
                fullName = s;
                acctNum = an;
                balance = bal;
            };
            inline void Deposit(double amt){
                if (amt < 0){
                    cout<<"Navigate deposit not allowed; deposit is cancelled."<<endl;
                }
                else{
                    balance += amt;
                }
            };
            //pure function[至少一个纯虚函数]，可实现可不实现
            virtual void Withdraw(double amt) = 0;
            //pure function[至少一个纯虚函数]，可实现可不实现
            virtual void ViewAcct()const = 0;
            double Balance()const{return balance;}
            //析构函数
            virtual ~AcctABC(){}
    };

    //子类实现
    class Brass : public AcctABC{
        public:
            inline Brass(const string &s="Nullbody",long an = -1,double bal = 0.0)
            :AcctABC(s,an,bal){
              //nothing to do here
            }
            virtual inline void Withdraw(double amt){
                if (amt < 0){
                    cout<<"Withdraw amount must be navigate; Withdraw will cancelled.";
                }
                else if(amt < Balance()){
                     AcctABC::Withdraw(amt);
                }
                else{
                    cout<<" Withdraw amount of $:"<<amt<<"exceed your banlance."<<endl<<"Withdrawal cancelled.";
                }
            };
           virtual inline void ViewAcct()const{
                Formatting f = setFormat();
                cout<<"Brass client:"<<FullName()<<endl;
                cout<<"Account Number:"<<AcctNum()<<endl;
                cout<<"Balance $:"<<Balance()<<endl;
                //恢复原始的格式化
                Restore(f);
           };
            virtual ~Brass(){}
    };

    //子类实现
    class BrassPlus: public AcctABC{
        private:
            double maxLoan;
            double rate;
            double owesBank;
        public:
            inline BrassPlus(const string &s="Nullbody",long an = -1,double bal = 0.0,
                             double m1 = 500,double r = 0.10)
                             :AcctABC(s,an,bal){
                maxLoan = m1;
                owesBank = 0.0;
                rate = r;
            };
            BrassPlus(const Brass &ba,double m1 = 500,double r = 0.10)
            :AcctABC(ba){
                maxLoan = m1;
                owesBank = 0.0;
                rate = r;
            };
            virtual inline void Withdraw(double amt){
                Formatting f = setFormat();
                double bal = Balance();
                if (amt <= bal){
                    AcctABC::Withdraw(amt);
                }
                else if(amt <=  bal + maxLoan  - owesBank){
                    double advance = amt - bal;
                    owesBank += advance * (1.0  + rate);
                    cout<<"Bank advance $:"<<advance<<endl;
                    cout<<"Finance charge $:"<<advance * rate<<endl;
                    Deposit(advance);
                    AcctABC::Withdraw(amt);
                }else{
                    cout<<"Credit limit exceeded .Transaction cancelled."<<endl;
                }

                //恢复原始的格式化
                Restore(f);
            };
            virtual inline void ViewAcct()const{
                Formatting f = setFormat();
                cout<<"BrassPlus client:"<<FullName()<<endl;
                cout<<"Account Number:"<<AcctNum()<<endl;
                cout<<"Balance $:"<<Balance()<<endl;
                cout<<"Maxloan $:"<<maxLoan<<endl;
                cout<<"owed to Bank $:"<<owesBank<<endl;
                cout.precision(3);
                cout<<"Loan cate :"<<100 * rate <<"%"<<endl;
                //恢复原始的格式化
                Restore(f);
            };

            //其他方法
            void ResetMax(double m){(*this).maxLoan = m;}
            void ResetRate(double r){(*this).rate = r;}
            void ResetOwes(){this->owesBank = 0;}
    };
}

#endif //CLION_CPP_T_PURE_VITURAL_FUNCTION_CLASS_H
